package aco;

import java.io.*;
import java.util.ArrayList;

// 通过此类读取算例数据，并记录算法的运算结果到硬盘
public class DataReader {
    private String filename;

    public DataReader(String filename) {
        this.filename = filename;
    }

    /**
     * 读取算例信息到VRPTW问题的vrp实例中，并返回此实例
     *
     * @return 问题实例
     */
    public VRPTW read() {
        VRPTW vrp = new VRPTW();
        VRPTW.instance = new VRPTW.Problem();
        ArrayList<Request> reqList = new ArrayList<Request>(); // 存储所有请求（包括静态和动态）
        ArrayList<Request> dynamicReqList = new ArrayList<Request>(); // 存储动态请求
        ArrayList<Integer> availableNodes = new ArrayList<Integer>(); // 可访问点

        if (filename.endsWith(".txt")) {
            boolean foundGeneralSection = false; // 车辆信息
            boolean foundRequestsSection = false; // 客户请求信息
            File file = new File("input/" + filename);
            BufferedReader br;
            if (file.exists()) {
                // 1.读算例数据
                VRPTW.instance.name = filename;
                try {
                    br = new BufferedReader(new FileReader(file));
                    String line = br.readLine();
                    while (line != null) {
                        // 1.如果是车辆信息行
                        if (foundGeneralSection) {
                            readGeneralRecord(line, vrp);
                            foundGeneralSection = false;
                        }

                        // 2.如果是客户请求信息行
                        if (foundRequestsSection) {
                            if (!line.trim().equals(""))
                                readRequestRecord(line, reqList, dynamicReqList, availableNodes);
                        }

                        // 3.判断下一行是车辆信息还是请求信息
                        if (line.startsWith("NUMBER")) {
                            foundGeneralSection = true;
                        }
                        if (line.startsWith("CUST NO.")) {
                            foundRequestsSection = true;
                        }

                        // 4.读取下一行
                        line = br.readLine();
                    }
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

                // 2.将文件中的数据写入问题vrp
                vrp.setRequests(reqList);
                vrp.setDynamicRequests(dynamicReqList);
                vrp.setIdAvailableRequests(availableNodes);
                int nrCustomerRequests = reqList.size() - 1;
                VRPTW.n = nrCustomerRequests;

                // 3.将算例数据写入到 instance 中
                VRPTW.instance.nodes = new VRPTW.Point[reqList.size()];
                for (int i = 0; i < reqList.size(); i++) {
                    VRPTW.instance.nodes[i] = new VRPTW.Point();
                    Request r = reqList.get(i);
                    VRPTW.instance.nodes[i].x = r.getxCoord();
                    VRPTW.instance.nodes[i].y = r.getyCoord();
                }
            }
        }
        return vrp;
    }

    /**
     * 读取文件开头的车辆信息：车辆数量、车辆载量
     * Read the first section of the input file containing the size of the vehicle fleet (vehicle number)
     * and the capacity of each vehicle
     *
     * @param line        string to extract the record from
     * @param vrpInstance reference to the VRPTW instance to be populated with the extracted data
     */
    private void readGeneralRecord(String line, VRPTW vrpInstance) {
        String strRecord[] = line.trim().split("\\s+");
        int values[] = new int[2];
        for (int i = 0; i < strRecord.length; i++) {
            try {
                values[i] = Integer.parseInt(strRecord[i]);
            } catch (NumberFormatException e) {
                System.out.println("NumberFormatException " + e.getMessage() + " record=" + strRecord[i] + " line=" + line);
            }
        }
        vrpInstance.setNoVehicles(values[0]);
        vrpInstance.setCapacity(values[1]);
    }

    /**
     * 读取工作日所有请求结点的信息，写入到总请求集合reqList中，写入到动态请求集合dynamicReqList中，并将静态请求的城市节点写入到可访问城市集合中
     * Read the requests section of the input file containing the list of the customers ' requests
     *
     * @param line    string to extract the record from
     * @param reqList reference to the list of requests to be populated with the extracted data
     */
    private void readRequestRecord(String line, ArrayList<Request> reqList, ArrayList<Request> dynamicReqList, ArrayList<Integer> availableNodes) {
        int cityId;
        int values[] = new int[8];
        String str[] = line.trim().split("\\s+");
        for (int i = 0; i < str.length; i++) {
            try {
                values[i] = Integer.parseInt(str[i]);
            } catch (NumberFormatException e) {

            }

        }
        Request req = new Request(values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7]);
        reqList.add(req);
        // dynamic customer request
        if (values[7] > 0) {
            dynamicReqList.add(req);
        }
        // keep separately the IDs of apriori requests/nodes which are available from the beginning, as part of DVRPTW instance
        else {
            //exclude the depot from the list of available nodes, since it is known by default that it is available (known)
            //substract 1, since the id/customer number of the first customer, except the depot, starts from 1
            // 仓库的id为-1，城市的id从0开始
            if (values[0] > 0) {
                cityId = values[0] - 1;
                availableNodes.add(cityId);
            }
        }
    }
}